#include "graphics.h"

static SDL_Window* window = NULL;
static SDL_Renderer* renderer = NULL;
static colour_t* colourBuffer = NULL;
static SDL_Texture* colourBufferTexture;

int initialiseWindow(void) {
  int fullScreenWidth;
  int fullScreenHeight;
  SDL_DisplayMode displayMode;

  if(SDL_Init(SDL_INIT_VIDEO) != 0) {
    fprintf(stderr, "Error initialising SDL.\n");
    return 0;
  }

  SDL_GetCurrentDisplayMode(0, &displayMode);
  fullScreenWidth = displayMode.w;
  fullScreenHeight = displayMode.h;
  
  window = SDL_CreateWindow(
                            NULL,
                            SDL_WINDOWPOS_CENTERED,
                            SDL_WINDOWPOS_CENTERED,
                            800, //fullScreenWidth,
                            600, //fullScreenHeight,
                            SDL_WINDOW_SHOWN
                            );
  if(!window) {
    fprintf(stderr, "Error creating SDL window.\n");
    return 0;
  }
  renderer = SDL_CreateRenderer(window, -1, 0);
  if(!renderer) {
    fprintf(stderr, "Error creating SDL renderer.\n");
    return 0;
  }
  SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);

    
  // allocate the total amount of bytes in memory to hold our colourBuffer
  colourBuffer = (colour_t*)malloc(WINDOW_WIDTH * WINDOW_HEIGHT * sizeof(colour_t));
  colourBufferTexture = SDL_CreateTexture(
                                          renderer,
                                          SDL_PIXELFORMAT_RGBA32,
                                          SDL_TEXTUREACCESS_STREAMING,
                                          WINDOW_WIDTH,
                                          WINDOW_HEIGHT
                                          );

  return 1;
}

void destroyWindow(void) {
  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);
  free(colourBuffer);
  SDL_Quit();
}

void clearColourBuffer(colour_t colour) {
  int x;
  for(x=0; x<WINDOW_WIDTH * WINDOW_HEIGHT; x++) {
    colourBuffer[x] = colour;
  }
}

void renderColourBuffer(void) {
  SDL_UpdateTexture(colourBufferTexture, NULL, colourBuffer, (int)(WINDOW_WIDTH * sizeof(colour_t)));
  SDL_RenderCopy(renderer, colourBufferTexture, NULL, NULL);
  SDL_RenderPresent(renderer);
}

void drawPixel(int x, int y, colour_t colour) {
  colourBuffer[(WINDOW_WIDTH * y) + x]  = colour;
}

void drawRect(int x, int y, int width, int height, colour_t colour) {
  int i, j;
  for(i=y; i<(height+y); i++)
    for(j=x; j<(width+x); j++)
      colourBuffer[(WINDOW_WIDTH * i) + j] = colour;
}

// DDA algorithm
void draw_line(int x0, int y0, int x1, int y1) {
  int delta_x = (x1 - x0);
  int delta_y = (y1 - y0);
  int i = 0;

  // find which side is greater
  int side_length = abs(delta_x) > abs(delta_y) ? abs(delta_x) : abs(delta_y);
  
  float x_inc = delta_x / (float)side_length;
  float y_inc = delta_y / (float)side_length;

  float current_x = x0;
  float current_y = y0;
  
  for(i=0; i<=side_length; i++){
    drawPixel(floor(current_x + 0.5), floor(current_y + 0.5), 0x0000FF);
    current_x += x_inc;
    current_y += y_inc;
  }	       
}

void changeColourIntensity(colour_t* colour, float factor) {
  colour_t a = (*colour & 0xFF000000);
  colour_t r = (*colour & 0x00FF0000) * factor;
  colour_t g = (*colour & 0x0000FF00) * factor;
  colour_t b = (*colour & 0x000000FF) * factor;
  *colour = a | (r & 0x00FF0000) | (g & 0x0000FF00) | (b & 0x000000FF);
}
